package se.sll.itintegration.catalogue.offer.ejb;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import lombok.extern.slf4j.Slf4j;
import se.sll.itintegration.catalogue.offer.entity.OfferEntity;
import se.sll.itintegration.catalogue.offer.entity.ProductReferenceEntity;
import se.sll.service.catalogue.common.AbstractJpaFacade;

/**
 *
 * @author khaleddaham
 * @author Jiri Uosukainen
 */
@Slf4j
@Stateless
public class OfferEjb extends AbstractJpaFacade<OfferEntity> {

    @PersistenceContext(unitName = "offerPU")
    private EntityManager em;

    public OfferEjb() {
        super(OfferEntity.class);
    }

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    @Override
    protected void setEntityManager(EntityManager em) {
        this.em = em;
    }

    @Override
    public void create(OfferEntity entity) {
        Timestamp ts = getTimeStamp();
        entity.setCreationTime(ts);
        entity.setUpdateTime(ts);
        super.create(entity);
    }

    /**
     *
     * @param name
     * @return
     */
    public List<OfferEntity> findByName(String name) {
        log.debug("findByName() was called");
        return super.findByAttributeValue("unitId", name);
    }

    /**
     * Gets the Offers (units) specified by input.
     *
     * @param unitIds A list of HSAID for the requested units. Not
     * <code>null</code>.
     * @return
     */
    public List<OfferEntity> findByUnits(Set<String> unitIds) {

        List<OfferEntity> foundUnits = em.createQuery("SELECT DISTINCT oe FROM OfferEntity oe WHERE oe.unitId IN :unitList", OfferEntity.class)
                .setParameter("unitList", unitIds).getResultList();

        if (foundUnits.size() != unitIds.size()) {
            log.warn("OfferEjb.findByUnits(): Found number of units differs from requested number of units");
            log.warn("OfferEjb.findByUnits(): Requested units: {}", unitIds);
            ArrayList<String> foundUnitIds = new ArrayList<>();
            for (OfferEntity oe : foundUnits) {
                foundUnitIds.add(oe.getUnitId());
            }
            log.warn("OfferEjb.findByUnits(): Found units: {}", foundUnitIds);
        }

        return foundUnits;
    }

    @SuppressWarnings("unchecked")
    public List<OfferEntity> findByProductReference(Set<String> productReferences) {
        Query queryProductsByName = em.createNamedQuery(OfferEntity.QUERY_FIND_BY_PRODUCT_NAME);
        queryProductsByName.setParameter("name", productReferences);
        return queryProductsByName.getResultList();
    }

    /**
     *
     * @param p
     */
    public void createProductReference(ProductReferenceEntity p) {
        getEntityManager().persist(p);
    }

    /**
     *
     * @param productName
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<OfferEntity> findByProductName(String productName) {
        Query queryProductsByName = em.createNamedQuery(OfferEntity.QUERY_FIND_BY_PRODUCT_NAME);
        queryProductsByName.setParameter("name", productName);
        return queryProductsByName.getResultList();
    }

    /**
     *
     * @param hsaID
     * @return
     */
    public OfferEntity findByUniqueName(String hsaID) {
        log.debug("findByUniqueName() was called");
        List<OfferEntity> peL = super.findByAttributeValue("unitId", hsaID);

        OfferEntity pe = null;
        if (peL != null && peL.size() == 1) {
            pe = peL.get(0);
        }
        return pe;
    }

    /**
     *
     * @param careUnitName
     * @return
     */
    public List<OfferEntity> findByCareUnitName(String careUnitName) {
        log.debug("findByCareUnitName() was called");
        return super.findByAttributeValue("relativeDistinguishedName", careUnitName);
    }

    public List<OfferEntity> findUpdatedSince(Date timeStamp) {
        log.debug("findUpdatedSince() was called");
        String qlString = "SELECT DISTINCT o FROM OfferEntity o WHERE o.updateTime > ?1";
        return getEntityManager().createQuery(qlString, OfferEntity.class).setParameter(1, timeStamp).getResultList();
    }

    public void deleteProductReference(ProductReferenceEntity p) {
        getEntityManager().remove(p);
    }
}
